package com.guagua.util;

import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.Callable;

import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.IMap;
import com.hazelcast.core.MultiMap;
import com.hazelcast.core.PartitionAware;

/**
 * 为分布式单例执行定义抽象类
 * <p>
 * 需要分布式单例执行时将业务逻辑写到该抽象类的实现类
 * 
 * @author 刘时运(shiyun@17guagua.com)
 * @version 2012-4-28 下午2:03:42
 * @param <Object>
 */
public abstract class HazelcastTask implements Callable<Object>, PartitionAware<Object>, Serializable {

	private static final long serialVersionUID = 1L;
	/**
	 * 需要支持分布式事务的map的名称
	 */
	private String mapName;
	/**
	 * 需要支持分布式事务map的key
	 */
	private Object mapKey;
	/**
	 * 需要支持分布式事务的map是否为MultiMap MultiMap为一个key可存多个值的的Map类型
	 */
	private boolean isMultiMap;

	public String getMapName() {
		return mapName;
	}

	public void setMapName(String mapName) {
		this.mapName = mapName;
	}

	public Object getMapKey() {
		return mapKey;
	}

	public void setMapKey(Object mapKey) {
		this.mapKey = mapKey;
	}

	public boolean isMultiMap() {
		return isMultiMap;
	}

	public void setMultiMap(boolean isMultiMap) {
		this.isMultiMap = isMultiMap;
	}

	public HazelcastTask(String mapName, Object mapKey, boolean isMultiMap) {
		super();
		this.mapName = mapName;
		this.mapKey = mapKey;
		this.isMultiMap = isMultiMap;
	}

	/**
	 * 单例执行的锁定键
	 */
	@Override
	public Object getPartitionKey() {
		return getMapKey();
	}

	/**
	 * 单例执行的逻辑处理
	 */
	@Override
	public Object call() throws Exception {
		Object returnValue = null;
		if (isMultiMap) {
			MultiMap<Object, Object> map = Hazelcast.getMultiMap(mapName);
			map.lock(mapKey);
			returnValue = businessWork(map.get(mapKey));
			map.unlock(mapKey);
		} else {
			IMap<Object, Object> map = Hazelcast.getMap(mapName);
			map.lock(mapKey);
			returnValue = businessWork(map);
			map.unlock(mapKey);
		}
		return returnValue;
	}

	/**
	 * 需要单例执行的业务逻辑
	 * <p>
	 * 需要实现类自己实现
	 * 
	 * @param map
	 *            从缓存服务器取出的缓存数据集合
	 * @return 分布式数据处理后 业务需要的值 根据实现返回
	 */
	protected abstract Object businessWork(Map<Object, Object> map);

	/**
	 * 需要单例执行的业务逻辑
	 * <p>
	 * 需要实现类自己实现
	 * 
	 * @param collection
	 *            从缓存服务器取出的对应key值缓存数据
	 * @return 分布式数据处理后 业务需要的值 根据实现返回
	 */
	protected abstract Object businessWork(Collection<Object> collection);
}
